package com.system.presideover.controller;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.system.common.config.exception.CustomException;
import com.system.common.config.exception.GlobalExceptionHandler;
import com.system.common.result.Result;
import io.swagger.annotations.Api;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.UUID;

/**
 * @author luYuHan
 * @date 2023/8/5 22:26
 */
@CrossOrigin(origins = "*")
@Controller
@Api(tags = "文件下载")
@RequestMapping("/presideover/file/upload")
public class MyFileUploadController {

    @Value("${aliyun.oss.file.endpoint}")
    private String endpoint;


    @Value("${aliyun.oss.file.accessKeyId}")
    private String accessKeyId;


    @Value("${aliyun.oss.file.accessKeySecret}")
    private String accessKeySecret;

    @Value("${aliyun.oss.file.bucketname}")
    private String bucketname;


    @Value("${urlVideo}")
    private String basePath;

    @PostMapping("/part")
    @ResponseBody
    public Result bigFile(HttpServletRequest request, String guid, Integer chunk, MultipartFile file, Integer chunks) {
        try {
            String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if (isMultipart) {
                if (chunk == null) chunk = 0;
                // 临时目录用来存放所有分片文件
                String tempFileDir = projectUrl + "/upload/" + guid;
                File parentFileDir = new File(tempFileDir);
                if (!parentFileDir.exists()) {
                    parentFileDir.mkdirs();
                }
                // 存放临时文件
                FileUtils.copyInputStreamToFile(file.getInputStream(), new File(parentFileDir, guid + "_chunk" + chunk + ".part"));
            }
        } catch (IOException e) {
            Result.fail().message("上传失败");
        }
        return Result.ok().message("上传成功");
    }


//    @PostMapping("/load")
//    @ResponseBody
//    public Result uploadFile(HttpServletRequest request, MultipartFile file) {
//
//        String filename = null;
//        try {
//            //获取文件名
//            String originalFilename = file.getOriginalFilename();
//            //获取文件格式
//            String subFile = originalFilename.substring(originalFilename.lastIndexOf("."));
//            //生成随机的文件名字
//            filename = UUID.randomUUID().toString() + subFile;
//            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
//
//            //TODO  对接oss
//
//            if (isMultipart) {
//                File file1 = new File(basePath);
//                //判断存放图片的目录是否存在，不存在则进行创建
//                if (!file1.exists()) {
//                    file1.mkdirs();
//                }
//                try {
//                    //错误示范
////            file.transferTo(new File(file1 + filename));
//                    //将临时文件转存到指定位置
//                    FileUtils.copyInputStreamToFile(file.getInputStream(), new File(basePath + filename));
////                    file.transferTo(new File(basePath + filename));
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//
//            }
//        }catch (Exception e) {
//            Result.fail(filename).message("上传失败");
//        }
//                return Result.ok(filename).message("上传成功");
//    }


//    @PostMapping("/load")
//    @ResponseBody
//    public Result uploadFile(HttpServletRequest request, MultipartFile file) {
//
//        // 创建OSSClient实例。
//        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//
////        String filename = null;
//            //获取文件名
//            String originalFilename = file.getOriginalFilename();
//            //获取文件格式
//            String subFile = originalFilename.substring(originalFilename.lastIndexOf("."));
//            //生成随机的文件名字
//            String  filename = UUID.randomUUID().toString() + subFile;
//
//        String objectName = "video/";
//        File file1 = new File(filename);
//        // 创建PutObjectRequest对象。
//        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketname, objectName, file1);
//        // 调用ossClient.putObject()方法上传文件。
//        PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
//        // 关闭OSSClient。
//        ossClient.shutdown();
//
////            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
////
////            //TODO  对接oss
////
////            if (isMultipart) {
////                File file1 = new File(basePath);
////                //判断存放图片的目录是否存在，不存在则进行创建
////                if (!file1.exists()) {
////                    file1.mkdirs();
////                }
////                try {
////                    //错误示范
//////            file.transferTo(new File(file1 + filename));
////                    //将临时文件转存到指定位置
////                    FileUtils.copyInputStreamToFile(file.getInputStream(), new File(basePath + filename));
//////                    file.transferTo(new File(basePath + filename));
////                } catch (IOException e) {
////                    e.printStackTrace();
////                }
////
////            }
////        }catch (Exception e) {
////            Result.fail(filename).message("上传失败");
////        }
//        return Result.ok(filename).message("上传成功");
//    }


//    @PostMapping("/load")
//    @ResponseBody
//    public Result uploadFile(MultipartFile file) {
//
//        //创建OSS对象
//        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
//
//        //获取原生文件名
//        String originalFilename = file.getOriginalFilename();
////        //JDK8的日期格式
////        LocalDateTime time = LocalDateTime.now();
////        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy/MM/dd");
////
////        //拼装OSS上存储的路径
////        String folder = dft.format(time);
//        String fileName = generateUUID();
//        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//
//        //在OSS上bucket下的文件名
//        String uploadFileName = "video/" + fileName + extension;
//
//        try {
//            PutObjectResult result = ossClient.putObject(bucketname, uploadFileName, file.getInputStream());
//            //拼装返回路径
//            if (result != null) {
////                String name = "https://"+bucketname+"."+extension+"/"+uploadFileName;
//                String name = "https://missok12.oss-cn-beijing.aliyuncs.com/"+uploadFileName;
//                return Result.ok(name).message("上传成功");
//            }
//        } catch (IOException e) {
////            log.error("文件上传失败:{}",e.getMessage());
//            return Result.fail().message("文件上传失败:{}");
//        } finally {
//            //OSS关闭服务，不然会造成OOM
//            ossClient.shutdown();
//        }
//
//        return Result.fail().message("上传失败！");
//    }


    @PostMapping("/load")
    @ResponseBody
    public Result uploadFile(MultipartFile file)  {


//        if (file.getSize() < 150 * 1024 * 1024){
//            try {
//                byte[] date = file.getBytes();
//        //获取原生文件名
//        String originalFilename = file.getOriginalFilename();
////        //JDK8的日期格式
////        //拼装OSS上存储的路径
//        String fileName = generateUUID();
//        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
//
//        //在OSS上bucket下的文件名
//        String uploadFileName = "video/" + fileName + extension;
//
//
//
//
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            } finally {
//            }
//        }

        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        //获取原生文件名
        String originalFilename = file.getOriginalFilename();
        String fileName = generateUUID();
        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));

        String objectName = "video/" + fileName + extension;

        try {
            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketname, objectName, new ByteArrayInputStream(file.getBytes()));
            // 执行上传，获取上传结果
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            if (result != null) {
                String name = "https://missok12.oss-cn-beijing.aliyuncs.com/"+objectName;
                return Result.ok(name).message("上传成功");
            }
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

            return Result.fail().message("上传失败！");
    }


    /**
     * 获取随机字符串
     *
     * @return
     */
    private String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

    /**
     * 文件下载
     * @param name
     * @param response
     */
//    @GetMapping("/download")
//    @ResponseBody
//    public void download(String name, HttpServletResponse response) {
//        try {
//            FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
//            //输出流，通过输出流将文件写回浏览器
//            ServletOutputStream outputStream = response.getOutputStream();
//
////            response.setContentType("video/mp4");
//
////            String suffixName = name.substring(name.lastIndexOf("."));
////            File finalFile = new File(basePath+suffixName);
////////            response.setContentType("image/jpeg");
////////            response.setContentType("video/mp4");
////            File allfile = new File(basePath);
////            for (File file : Objects.requireNonNull(allfile.listFiles())) {
////                fileOutputStream = new FileOutputStream(finalFile,true);
////                long l = FileUtils.copyFile(file, fileOutputStream);
////
////                outputStream.write((int) l);
////                outputStream.flush();
////            }
////            int len = 0;
//            File finalFile = new File(basePath+name.substring(name.lastIndexOf(".")));
//            FileOutputStream fileOutputStream = null;
//            File allfile = new File(basePath+name);
//            for (File file : Objects.requireNonNull(allfile.listFiles())) {
//                fileOutputStream = new FileOutputStream(finalFile,true);
//                long l = FileUtils.copyFile(file, fileOutputStream);
//                outputStream.write((int) l);
//                outputStream.flush();
//            }
//
//            fileOutputStream.close();
//            outputStream.close();
//            fileInputStream.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//
//
//    }


//    @GetMapping("/download")
//    public void download(String name, HttpServletResponse response) {
//
//        //TODO  对接oss下载回显
//
//        try {
//            FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
//            //输出流，通过输出流将文件写回浏览器
//            ServletOutputStream outputStream = response.getOutputStream();
//
////            response.setContentType("image/jpeg");
//            response.setContentType("video/mp4");
//            int len;
////            byte[] bytes = new byte[1024];
//            byte[] bytes = new byte[4096];
//            while ((len = fileInputStream.read(bytes)) != -1){
//                outputStream.write(bytes,0,len);
//                outputStream.flush();
//            }
//            outputStream.close();
//            fileInputStream.close();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }


    /**
     * oss实现下载
     *
     * @param name
     * @param response
     */
    @GetMapping("/download")
    public void download(String name, HttpServletResponse response) {

        //TODO  对接oss下载回显

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);


        String objectKey = "video/" + name;

        try {
            // 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元数据。
            OSSObject ossObject = ossClient.getObject(bucketname, objectKey);
            // 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
            InputStream content = ossObject.getObjectContent();
            if (content != null) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(content));
                while (true) {
                    String line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    System.out.println("\n" + line);
                }
                // 数据读取完成后，获取的流必须关闭，否则会造成连接泄漏，导致请求无连接可用，程序无法正常工作。
                content.close();
            }
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException io) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + io.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

//        try {
//            // 创建获取文件的请求
//            String objectKey = "video/";
//            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketname, objectKey);
//
//            // 通过OSSClient对象执行获取文件的请求，返回OSSObject对象
//            OSSObject ossObject = ossClient.getObject(getObjectRequest);
//
//            // 获取OSSObject对象的内容流
//            InputStream inputStream = ossObject.getObjectContent();
//
//            response.setContentType("image/jpeg");
//            response.setContentType("video/mp4");
//
//            // 创建本地文件输出流
//            FileOutputStream fileOutputStream = new FileOutputStream(new File(name));
//
//            // 将OSSObject对象的内容流写入本地文件
////            byte[] buffer = new byte[4096];
////            byte[] buffer = new byte[8192];
//            byte[] buffer = new byte[16384];
//            int len;
//            while ((len = inputStream.read(buffer)) != -1) {
//                fileOutputStream.write(buffer, 0, len);
//            }
//            // 关闭流
//            fileOutputStream.close();
//            inputStream.close();
//
//            System.out.println("文件下载成功！");
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            // 关闭OSSClient
//            ossClient.shutdown();
//        }


    }


    @GetMapping("merge")
    @ResponseBody
    public Result mergeFile(String guid, String fileName) {
        try {
            // 得到 destTempFile 就是最终的文件
            String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            String finaFileName = projectUrl + "/upload/" + UUID.randomUUID() + suffixName;
            String temFileDir = projectUrl + "/upload/" + guid;
            File finalFile = new File(finaFileName);
            File allfile = new File(temFileDir);
            for (File file : Objects.requireNonNull(allfile.listFiles())) {
                FileOutputStream fileOutputStream = new FileOutputStream(finalFile, true);
                FileUtils.copyFile(file, fileOutputStream);
                fileOutputStream.close();
            }
        } catch (IOException e) {
            return Result.fail().message("合并失败");
        }
        return Result.ok().message("合并成功");

    }


    @GetMapping("/video/download")
    @ResponseBody
    public Result downloadVideo(@RequestParam String filename, HttpServletResponse response) {
        Path path = Paths.get(basePath + filename);
        File file = path.toFile();

        // 检查文件是否存在
        if (!file.exists()) {
            new GlobalExceptionHandler().error(new CustomException(205, "文件未找到！"));
        }

        response.setContentType("video/mp4");
        // 初始化进度监听器（这里可以是数据库、消息队列等）
        // ...

        StreamingResponseBody streamingResponse = outputStream -> {
            try (FileInputStream inputStream = new FileInputStream(file)) {
                byte[] buffer = new byte[4096];
                int bytesRead;

                // 读取文件内容并写入响应输出流
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    // 更新进度监听器（发送进度信息到数据库、消息队列等）
                    // ...

                    outputStream.write(buffer, 0, bytesRead);
                    outputStream.flush();
                }
            } catch (IOException e) {
                // 处理异常，例如记录日志、发送错误通知等
                // ...
                e.printStackTrace();
            }
        };

//        return ResponseEntity.ok()
//                .contentType("video/mp4")
//                .header("Content-Disposition", "attachment; filename=\"" + filename + "\"")
//                .body(streamingResponse);

        return Result.ok(streamingResponse);
    }


    /**
     * oss实现下载
     *
     * @param name
     * @param response
     */
    @PostMapping("/delectVideo")
    public void delectprcture(String name, HttpServletResponse response) {

        //TODO  对接oss下载回显

        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        String subFile = name.substring(name.lastIndexOf("video/"));
//        String str = name.substring(name.lastIndexOf("/"));
//        String[] parts = str.split("/");
//        String s_without_slash = parts.length > 0 ? parts[1] : "";

        try {
            // 删除文件。
            ossClient.deleteObject(bucketname, subFile);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

}
